package cn.iocoder.yudao.boot.common.util.context;

import cn.iocoder.yudao.boot.common.constant.ContextConstant;
import cn.iocoder.yudao.boot.common.pojo.LoginUser;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 全局上下文
 */
public class ContextHolder {
    // 使用ThreadLocal确保每个线程都有自己的上下文Map
    private static final ThreadLocal<ConcurrentHashMap<String, Object>> CONTEXT_HOLDER =
            ThreadLocal.withInitial(ConcurrentHashMap::new);

    // 私有构造函数，防止外部实例化
    private ContextHolder() {}

    // 设置上下文数据
    public static <T> void set(String key, T value) {
        CONTEXT_HOLDER.get().put(key, value);
    }

    // 根据键和类型参数获取上下文数据
    public static <T> Optional<T> get(String key, Class<T> type) {
        Object value = CONTEXT_HOLDER.get().get(key);
        if (value != null && type.isInstance(value)) {
            return Optional.ofNullable(type.cast(value));
        }
        return Optional.empty();
    }

    // 清除当前线程的上下文数据
    public static void clear() {
        CONTEXT_HOLDER.remove();
    }

    // 清除指定键的上下文数据
    public static void remove(String key) {
        CONTEXT_HOLDER.get().remove(key);
    }

    // 获取当前线程的上下文Map（通常用于调试或特殊情况）
    public static ConcurrentHashMap<String, Object> getContextMap() {
        return CONTEXT_HOLDER.get();
    }

    public static void setLoginUser(LoginUser loginUser){
        set(ContextConstant.LOGIN_USER, loginUser);
    }

    public static Optional<LoginUser> getLoginUser(){
        return get(ContextConstant.LOGIN_USER, LoginUser.class);
    }

    public static Optional<Long> getLoginUserId(){
        Optional<LoginUser> loginUserOps = get(ContextConstant.LOGIN_USER, LoginUser.class);
        return loginUserOps.map(loginUser -> loginUser.getId());
    }

    public static Optional<Integer> getLoginUserType(){
        Optional<LoginUser> loginUserOps = get(ContextConstant.LOGIN_USER, LoginUser.class);
        return loginUserOps.map(loginUser -> loginUser.getUserType());
    }

    public static Optional<Long> getTenantId(){
        Optional<LoginUser> loginUserOps = get(ContextConstant.LOGIN_USER, LoginUser.class);
        return loginUserOps.map(loginUser -> loginUser.getTenantId());
    }
}
